from datetime import datetime
from queue import Queue
import threading
import json

from pandas import DataFrame

from common.pd import get_tb_data, DF_Table, get_tb_datas_counts
from common.utils import get_day_differ, datetime_str_to_datetime, timeit
from common.utils import get_today_str, get_now_str
from common.mydb import Table
from common.singleton import singleton
from common.config import public_data

from project.web_comm import get_token
from project.file import get_once_json


# 合同数据表


# 文件更新日期数据表的查询与
@singleton
class Tb_Message(Table):
    def __init__(self):
        super().__init__("message")
        self.col_list = ["id", "ms_name", "ms_date", "ms_value"]
        self.update_col_list = ["ms_value"]
        self.key_col = "ms_name"

    def get_data(self, ms_name):
        return self.find_one(f" ms_name='{ms_name}'")

    def update_tb_message(self, ms_name, ms_value):
        data = self.get_data(ms_name)
        if data:
            self.update_one_col("ms_value", ms_value, f" ms_name='{ms_name}'")
        else:
            ms_date = get_now_str()
            self.insert_row([ms_name, ms_date, ms_value])

    def get_update_file_date(self):
        data = self.get_data('update_file')
        if data:
            print(data)
            return data[3]

    def update_file_date(self):
        update_date = get_today_str()
        self.update_tb_message("file_update", update_date)


# endregion


# region 合同相关信息功能
def get_contract_by_lot_code(lot_code_str):
    """
    通过采购包信息获取合同信息
    """
    return get_tb_data("contract", f"lot_code like '%{lot_code_str}%'")


# endregion

# region 文函处理
# 处理函件Json
def dic_to_fax(file_json: dict, contract: list) -> dict:
    """
    contract:["id", "project", "channel_code", "lot_code", "factory",""author_code""]
    将页面函件信息字典转为函件表的字典信息
    """
    fax = dict()
    # region 设置初始值:
    """
    { 'once_id':"", 
      'fax_type', 
      'channel', 
      'code',
      'title', 
      'date_effect', 
      'reply_fax', 
      'replied_fax',
       'note', 
      'invalid', 
      'contract_id', 
      'look_up_str'}
    """
    fax["once_id"] = 0
    fax["fax_type"] = ""
    fax["channel"] = ""
    fax["code"] = ""
    fax["title"] = ""
    fax["date_effect"] = ""
    fax["reply_fax"] = ""
    fax["replied_fax"] = ""
    fax["note"] = ''
    fax["invalid"] = 0
    fax["contract_id"] = 0
    fax["look_up_str"] = ''
    # end region
    fax["contract_id"] = contract[0]
    fax["once_id"] = file_json["id"]
    fax["title"] = file_json["description"]
    fax["channel"] = file_json["title"].strip()
    fax["invalid"] = 1 if file_json["INV"] else 0
    for info_dic in file_json["otherFields"]:
        if info_dic["code"] == "c_letter_type":
            fax["fax_type"] = info_dic["value"]
        if info_dic["code"] == "c_valid_date":
            fax["date_effect"] = info_dic["value"]
        if info_dic["code"] == "c_reply_channel":
            fax["reply_fax"] = info_dic["value"]
        if info_dic["code"] == "reply_to_channel":
            fax["replied_fax"] = info_dic["value"]
    result = file_json["highLightingFields"]
    if result:
        if "被答复渠道号" in result:
            fax["replied_fax"] = get_channel(result, "被答复渠道号")
        if "回文号" in result:
            fax["reply_fax"] = get_channel(result, "回文号")
    # contract:{contract[0]},project:{contract[1]},lot_code:{contract[3]},factory: {contract[4]},
    fax["look_up_str"] = f'file:{fax["channel"]}, {fax["title"]} {fax["date_effect"]} '
    return fax


# 处理文件json
def dic_to_doc(file_json: dict, contract: list):
    """返回
    {"doc_type": doc_type, "doc": document}
    doc_type: "doc_f" ,"doc_e"
    """
    document = {'once_id': "", 'code': "", 'rev': "", 'inner_code': "", 'title': "", 'date_public': "", 'newest': 1,
                'doc_type': "", 'channel': "", 'reviewed': 0, 'reviewed_result': "", 'drcs_channel': "", 'file_name': "",
                'author_code': "", 'note': "", 'invalid': 0, "is_wr": 1, 'contract_id': 0,
                'look_up_str': ""}
    document["contract_id"] = contract[0]
    document["once_id"] = file_json["id"]
    document["newest"] = 1 if file_json["NEW"] else 0

    document["is_wr"] = 1 if file_json["WR"] else 0
    document["title"] = file_json["firstFields"][0]["hlValue"]
    document["file_name"] = file_json["title"]

    for info_data in file_json["otherFields"]:
        if info_data["code"] == "c_record_code":
            document["code"] = info_data["value"].strip()
            continue
        if info_data["code"] == "c_revision":
            document["rev"] = info_data["value"]
            continue
        if info_data["code"] == "c_internal_identity":
            document["inner_code"] = info_data["value"]
            continue
        if info_data["code"] == "c_transmital_channel":
            channel_code_str = info_data["value"]

            channels = channel_code_str.split()
            for channel in channels:
                if contract[2] in channel:
                    document["channel"] = channel.strip()
                    break
            continue
        if info_data["code"] == "c_valid_date":
            document['date_public'] = info_data["value"]
            continue
        if info_data["code"] == "c_review_channel":
            document['drcs'] = info_data["value"]

        document['author_code'] = document["code"][11:15]
    # 文件审查
    result = file_json["highLightingFields"]
    doc_type = "doc_e"
    document["reviewed"] = 0
    if contract[-1] in document["code"] and result:
        doc_type = "doc_f"

        if "review_result" in result:
            reviewed_result = ""
            if "ACC" in result:
                reviewed_result = "ACC"
            if "AEN" in result:
                reviewed_result = "AEN"
            if "RFC" in result:
                reviewed_result = "RFC"
            if reviewed_result:
                document["reviewed_result"] = reviewed_result
                document["reviewed"] = 1
    #  查询字段包含 项目+采购包+制造厂+finish=1+文件名+标题+内部编码+通道号+生效日期+合同id
    doc_status_info = f'reviewed={document["reviewed"]},newest={document["newest"]} ,'
    doc_info = f'file:{document["channel"]} ,{document["file_name"]} ,{document["title"]} ,{document["inner_code"]}, {document["date_public"]}'
    document["look_up_str"] = doc_status_info + doc_info

    return {"doc_type": doc_type, "doc": document}


# 将文函信息存到数据库
def file_data_to_db() -> str:
    """
    将转化的文函字典列表传送至数据库
    data_dic :{"faxes": fax_list, "doc_e": doc_e_list, "doc_f": doc_f_list}
    """
    fax_tb = DF_Table("fax")
    doc_e_tb = DF_Table("doc_e")
    doc_f_tb = DF_Table("doc")
    if public_data.update_all:
        fax_tb.clear_data()
        doc_f_tb.clear_data()
        doc_e_tb.clear_data()
    i = 0
    while True:
        file_queue = public_data.file_dic_list_queue
        data_dic = file_queue.get()
        if file_queue == "end":
            print("已更新完成")
            return "已更新完成"
        try:
            doc_f_list = data_dic["doc_f"]
            fax_list = data_dic["faxes"]
            doc_e_list = data_dic["doc_e"]

            if doc_e_list:
                print("doc_e", i, len(doc_e_list), sep="-")
                doc_e_tb.file_dict_list_to_table(doc_e_list)

            if doc_f_list:
                print("doc_f", i, len(doc_e_list), sep="-")
                doc_f_tb.file_dict_list_to_table(doc_f_list)
            if fax_list:
                fax_tb.file_dict_list_to_table(fax_list)

            i += 1
        except Exception as e:
            print(e)


# 将文函信息进行处理为数据表字典，并放入public_data.file_dic_list_queue
def file_json_to_queue():
    """将文函信息进行处理为数据表字典，并放入public_data.file_dic_list_queue"""
    while True:
        json_queue: Queue = public_data.file_json_queue
        result = "更新关闭"
        json_dic = json_queue.get()
        if json_dic == "end":
            return result

        data = classify_file_dic(json_dic)
        public_data.file_dic_list_queue.put(data)


def classify_file_dic(json_dic: dict) -> dict:
    """
    将文函信息进行处理为数据表字典，
    返回值 {"faxes": fax_list, "doc_e": doc_e_list, "doc_f": doc_f_list}
    """

    contract: list = json_dic["contract"]
    file_dices = json_dic["file_dic"]
    doc_f_list = []
    fax_list = []
    doc_e_list = []
    for file_dic in file_dices:
        if 'LETTERS' in file_dic["category"]:
            fax_list.append(dic_to_fax(file_dic, contract))
        elif 'TECHDOCS' in file_dic["category"]:
            doc = dic_to_doc(file_dic, contract)
            if doc["doc_type"] == "doc_e":
                doc_e_list.append(doc["doc"])
            else:
                doc_f_list.append(doc["doc"])
    return {"faxes": fax_list, "doc_e": doc_e_list, "doc_f": doc_f_list}


# endregion
# endregion

def get_token_to_public_data():
    token = get_token()
    data = public_data
    data.Token = token
    if data.Token:
        data.Token_time = datetime.now()


@timeit
def update_contracts_file():
    """
    采用多线程获取once中合同的文函信息放入 public_data.file_json_queue 中
    文函信息格式：{"contract": contract, "file_dic": file_dices}
    更新完成后，发送字符串 "end"
    """
    df_contract = public_data.Df_Contract
    if df_contract.empty:  # 检查是否有合同信息
        return "无合同信息"
    if not public_data.Token:  # 检查是否有Token
        get_token_to_public_data()
        if not public_data.Token:
            return "获取身份验证信息不成功"
    # period = __get_period()  # 获取需要更新的周期
    contract_list = df_contract[["id", "project", "channel_code", "lot_code", "factory", "author_code"]].values.tolist()
    threads = [threading.Thread(target=get_one_file, args=(contract,)) for contract in contract_list]
    for thread in threads:
        thread.start()
    thread_file_to_queue = threading.Thread(target=file_json_to_queue)  # 将处理的文件信息放入队列
    thread_file_to_queue.start()
    thread_file_to_db = threading.Thread(target=file_data_to_db)  # 将处理的文件信息放入队列
    thread_file_to_db.start()
    file_data_to_db()
    # 等待子程序结束
    for thread in threads:
        thread.join()
    print("获取网络文件完成")
    queue: Queue = public_data.file_json_queue
    queue.put("end")
    thread_file_to_queue.join()
    # 给两个队列传送结束标志字符串

    file_queue = public_data.file_dic_list_queue
    file_queue.put("end")
    print("文函分类处理完成")
    thread_file_to_db.join()
    print("文件存储数据库完成")


# 获取一个合同的文函信息
def get_one_file(contract):
    """
    para: contract 格式 ["id","project","channel_code"]
    根据合同信息获取合同的文函信息
    文函信息格式：{"contract": contract, "file_dic": file_dices}
    """
    project = contract[1]
    channel_code = contract[2]
    page_index = 1
    unfinished = True
    while unfinished:
        text_json = get_once_json(project, channel_code, index_page=page_index)
        if text_json:
            file_dices = text_json['resultList']
            queue: Queue = public_data.file_json_queue
            queue.put({"contract": contract, "file_dic": file_dices})
            if text_json["recordCount"] <= 1000 * page_index:
                unfinished = False
            else:
                page_index += 1


def get_channel(info_str: str, label_str: str):
    data0 = info_str.split(label_str)[-1]
    data1 = data0.split("】")
    data2 = data1[1].split("<")
    return data2[0]


# region 处理 更新周期
def __get_update_differ_days():
    tb_message = Tb_Message()
    last_update_day_str = tb_message.get_update_file_date()
    # print(last_update_day_str)
    last_update_time = datetime_str_to_datetime(last_update_day_str)
    # print(last_update_day)
    return get_day_differ(last_update_time, datetime.now()) + 1


def __get_period():
    """
    计算本次查询的时间差
    period: [-week,  -month,  -quarter 三个月,  -halfyear, -year]
    """
    date_diff = __get_update_differ_days()
    print(date_diff)
    if date_diff < 7:
        period = "-week"
    if 7 < date_diff <= 30:
        period = "-month"
    elif 30 < date_diff <= 120:
        period = " -quarter"
    elif 120 < date_diff <= 180:
        period = " -halfyear"
    elif 180 < date_diff <= 365:
        period = " -year"
    else:
        period = ""
    return period


# endregion


# region 和视图层的接口

# 获取合同信息
def get_contract_df(condition=None) -> DataFrame:
    """获取数据库中的合同信息"""

    return get_tb_data("contract", condition)


# 获取制造厂的文函
def get_all_doc_factory(condition=None):
    return get_tb_data("doc", condition)


def get_doc_factory(count):
    return get_tb_datas_counts("doc", count)


public_data.Df_Contract = get_contract_df()


def get_tb_drcs(condition=None):
    """获取数据表中的drcs信息"""
    drcs_df = get_tb_data("drcs", condition)
    if not drcs_df.empty:
        drcs_list = []
        drcs_df_dic = drcs_df.to_dict()
        channel_dic: dict = drcs_df_dic["file_channel"]
        keys = channel_dic.keys()
        drcs_list = []
        for key in keys:

            if channel_dic[key]:
                id = drcs_df_dic['id'][key]
                title = drcs_df_dic['title'][key]
                comment = drcs_df_dic['comment'][key]
                checker = drcs_df_dic["checker"][key]
                approver = drcs_df_dic["approver"][key]
                cc = drcs_df_dic["cc"][key]
                contract_id = drcs_df_dic["contract_id"][key]
                url = drcs_df_dic["url"][key]
                channel = drcs_df_dic["channel"][key]
                project = drcs_df_dic["project"][key]
                receiver_code = drcs_df_dic["receiver_code"][key]
                doc_json = drcs_df_dic["doc_json"][key]
                docs_dic = json.loads(doc_json)
                status = drcs_df_dic["status"][key]

                drcs_dict = {
                    "id": id,
                    "file_channel": channel_dic[key],
                    "cc": cc,
                    "title": title,
                    "comment": comment,
                    "sys_attch": "",
                    "checker": checker,
                    "approver": approver,
                    "url": url,
                    "contract_id": contract_id,
                    "channel": channel,
                    "project": project,
                    "receiver_code": receiver_code,
                    "doc_dic": docs_dic,
                    "status": status
                }
                drcs_list.append(drcs_dict)
        return drcs_list

# endregion
